using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using NUnit.Framework;
using ValidationFramework.WPF;

namespace ValidationFramework.Tests.WPF
{
    public class ValidationBindingTest
    {
        [TestFixture]
        public class Construction
        {
            [Test]
            public void Default()
            {
                var validationBinding = new ValidationBinding();
                Assert.IsNull(validationBinding.AsyncState);
                Assert.IsFalse(validationBinding.BindsDirectlyToSource);
                Assert.IsNull(validationBinding.Context);
                Assert.IsNull(validationBinding.Converter);
                Assert.IsNull(validationBinding.ConverterCulture);
                Assert.IsNull(validationBinding.ConverterParameter);
                Assert.IsNull(validationBinding.ElementName);
                Assert.AreEqual(DependencyProperty.UnsetValue, validationBinding.FallbackValue);
                Assert.IsFalse(validationBinding.IsAsync);
                Assert.AreEqual(BindingMode.Default, validationBinding.Mode);
                Assert.IsTrue(validationBinding.NotifyOnTargetUpdated);
                Assert.IsFalse(validationBinding.NotifyOnValidationError);
                Assert.IsNull(validationBinding.Path);
                Assert.IsNull(validationBinding.RelativeSource);
                Assert.IsNull(validationBinding.RuleSet);
                Assert.IsNull(validationBinding.Source);
                Assert.IsNull(validationBinding.UpdateSourceExceptionFilter);
                Assert.AreEqual(UpdateSourceTrigger.PropertyChanged, validationBinding.UpdateSourceTrigger);
                Assert.AreEqual(0, validationBinding.ValidationRules.Count);
                Assert.IsNull(validationBinding.XPath);
            }
            [Test]
            public void DefaultPath()
            {
                var validationBinding = new ValidationBinding("ExpectedPath");
                Assert.IsNull(validationBinding.AsyncState);
                Assert.IsFalse(validationBinding.BindsDirectlyToSource);
                Assert.IsNull(validationBinding.Context);
                Assert.IsNull(validationBinding.Converter);
                Assert.IsNull(validationBinding.ConverterCulture);
                Assert.IsNull(validationBinding.ConverterParameter);
                Assert.IsNull(validationBinding.ElementName);
                Assert.AreEqual(DependencyProperty.UnsetValue, validationBinding.FallbackValue);
                Assert.IsFalse(validationBinding.IsAsync);
                Assert.AreEqual(BindingMode.Default, validationBinding.Mode);
                Assert.IsTrue(validationBinding.NotifyOnTargetUpdated);
                Assert.IsFalse(validationBinding.NotifyOnValidationError);
                Assert.IsNotNull(validationBinding.Path);
                Assert.AreEqual("ExpectedPath", validationBinding.Path.Path);
                Assert.IsNull(validationBinding.RelativeSource);
                Assert.IsNull(validationBinding.RuleSet);
                Assert.IsNull(validationBinding.Source);
                Assert.IsNull(validationBinding.UpdateSourceExceptionFilter);
                Assert.AreEqual(UpdateSourceTrigger.PropertyChanged, validationBinding.UpdateSourceTrigger);
                Assert.AreEqual(0, validationBinding.ValidationRules.Count);
                Assert.IsNull(validationBinding.XPath);
            }
            [Test]
            public void NonDefaultRelativeSource()
            {
                var validationBinding = new ValidationBinding
                                            {
                                                AsyncState = new object(),
                                                BindsDirectlyToSource = true,
                                                Context = new object(),
                                                Converter = new BooleanToVisibilityConverter(),
                                                ConverterCulture = CultureInfo.CurrentCulture,
                                                ConverterParameter=new object(),
                                                FallbackValue=new object(),
                                                IsAsync=true,
                                                Mode=BindingMode.OneTime,
                                                NotifyOnTargetUpdated=true,
                                                NotifyOnValidationError=false,
                                                Path=new PropertyPath("ExpectedPath"),
                                                RelativeSource=RelativeSource.PreviousData,
                                                RuleSet="ExpectedRuleSet",
                                                UpdateSourceExceptionFilter=CallBack,
                                                UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
                                                XPath="ExpectedXPath"
                                            };
                Assert.IsNotNull(validationBinding.AsyncState);
                Assert.IsTrue(validationBinding.BindsDirectlyToSource);
                Assert.IsNotNull(validationBinding.Context);
                Assert.IsNotNull(validationBinding.Converter);
                Assert.IsNotNull(validationBinding.ConverterCulture);
                Assert.IsNotNull(validationBinding.ConverterParameter);
                Assert.IsNull(validationBinding.ElementName);
                Assert.IsNotNull(validationBinding.FallbackValue);
                Assert.IsTrue(validationBinding.IsAsync);
                Assert.AreEqual(BindingMode.OneTime, validationBinding.Mode);
                Assert.IsTrue(validationBinding.NotifyOnTargetUpdated);
                Assert.IsFalse(validationBinding.NotifyOnValidationError);
                Assert.IsNotNull(validationBinding.Path);
                Assert.IsNotNull(validationBinding.RelativeSource);
                Assert.IsNotNull(validationBinding.RuleSet);
                Assert.IsNull(validationBinding.Source);
                Assert.IsNotNull(validationBinding.UpdateSourceExceptionFilter);
                Assert.AreEqual(UpdateSourceTrigger.Explicit, validationBinding.UpdateSourceTrigger);
                Assert.AreEqual(0, validationBinding.ValidationRules.Count);
                Assert.IsNotNull(validationBinding.XPath);
            }
            [Test]
            public void NonDefaultElementName()
            {
                var validationBinding = new ValidationBinding
                                            {
                                                AsyncState = new object(),
                                                BindsDirectlyToSource = true,
                                                Context = new object(),
                                                Converter = new BooleanToVisibilityConverter(),
                                                ConverterCulture = CultureInfo.CurrentCulture,
                                                ConverterParameter=new object(),
                                                ElementName="ExpectedElementName",
                                                FallbackValue=new object(),
                                                IsAsync=true,
                                                Mode=BindingMode.OneTime,
                                                NotifyOnTargetUpdated=true,
                                                NotifyOnValidationError=false,
                                                Path=new PropertyPath("ExpectedPath"),
                                                RuleSet="ExpectedRuleSet",
                                                UpdateSourceExceptionFilter=CallBack,
                                                UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
                                                XPath="ExpectedXPath"
                                            };
                Assert.IsNotNull(validationBinding.AsyncState);
                Assert.IsTrue(validationBinding.BindsDirectlyToSource);
                Assert.IsNotNull(validationBinding.Context);
                Assert.IsNotNull(validationBinding.Converter);
                Assert.IsNotNull(validationBinding.ConverterCulture);
                Assert.IsNotNull(validationBinding.ConverterParameter);
                Assert.IsNotNull(validationBinding.ElementName);
                Assert.IsNotNull(validationBinding.FallbackValue);
                Assert.IsTrue(validationBinding.IsAsync);
                Assert.AreEqual(BindingMode.OneTime, validationBinding.Mode);
                Assert.IsTrue(validationBinding.NotifyOnTargetUpdated);
                Assert.IsFalse(validationBinding.NotifyOnValidationError);
                Assert.IsNotNull(validationBinding.Path);
                Assert.IsNull(validationBinding.RelativeSource);
                Assert.IsNotNull(validationBinding.RuleSet);
                Assert.IsNull(validationBinding.Source);
                Assert.IsNotNull(validationBinding.UpdateSourceExceptionFilter);
                Assert.AreEqual(UpdateSourceTrigger.Explicit, validationBinding.UpdateSourceTrigger);
                Assert.AreEqual(0, validationBinding.ValidationRules.Count);
                Assert.IsNotNull(validationBinding.XPath);
            }
            [Test]
            public void NonDefaultSource()
            {
                var validationBinding = new ValidationBinding
                                            {
                                                AsyncState = new object(),
                                                BindsDirectlyToSource = true,
                                                Context = new object(),
                                                Converter = new BooleanToVisibilityConverter(),
                                                ConverterCulture = CultureInfo.CurrentCulture,
                                                ConverterParameter=new object(),
                                                FallbackValue=new object(),
                                                IsAsync=true,
                                                Mode=BindingMode.OneTime,
                                                NotifyOnTargetUpdated=true,
                                                NotifyOnValidationError=false,
                                                Path=new PropertyPath("ExpectedPath"),
                                                RuleSet="ExpectedRuleSet",
                                                Source=new object(),
                                                UpdateSourceExceptionFilter=CallBack,
                                                UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
                                                XPath="ExpectedXPath"
                                            };
                Assert.IsNotNull(validationBinding.AsyncState);
                Assert.IsTrue(validationBinding.BindsDirectlyToSource);
                Assert.IsNotNull(validationBinding.Context);
                Assert.IsNotNull(validationBinding.Converter);
                Assert.IsNotNull(validationBinding.ConverterCulture);
                Assert.IsNotNull(validationBinding.ConverterParameter);
                Assert.IsNull(validationBinding.ElementName);
                Assert.IsNotNull(validationBinding.FallbackValue);
                Assert.IsTrue(validationBinding.IsAsync);
                Assert.AreEqual(BindingMode.OneTime, validationBinding.Mode);
                Assert.IsTrue(validationBinding.NotifyOnTargetUpdated);
                Assert.IsFalse(validationBinding.NotifyOnValidationError);
                Assert.IsNotNull(validationBinding.Path);
                Assert.IsNull(validationBinding.RelativeSource);
                Assert.IsNotNull(validationBinding.RuleSet);
                Assert.IsNotNull(validationBinding.Source);
                Assert.IsNotNull(validationBinding.UpdateSourceExceptionFilter);
                Assert.AreEqual(UpdateSourceTrigger.Explicit, validationBinding.UpdateSourceTrigger);
                Assert.AreEqual(0, validationBinding.ValidationRules.Count);
                Assert.IsNotNull(validationBinding.XPath);
            }

            private static object CallBack(object bindExpression, Exception exception)
            {
                throw new NotImplementedException();
            }
        }

        [TestFixture]
        public class AddErrorDisplayStrategy
        {

            [Test]
            [ExpectedException(typeof(ArgumentNullException))]
            public void ExceptionNullStrategy()
            {
                ValidationBinding.DisplayStrategies.AddStrategy(null);
            }
        [Test]
            public void Simple()
            {
            var mockErrorDisplayStrategy = new MockErrorDisplayStrategy();
			ValidationBinding.DisplayStrategies.AddStrategy(mockErrorDisplayStrategy);
            Assert.IsTrue(ValidationBinding.DisplayStrategies.Contains(mockErrorDisplayStrategy));
            }
        }

        [TestFixture]
        public class RemoveErrorDisplayStrategy
        {

            [Test]
            [ExpectedException(typeof(ArgumentNullException))]
            public void ExceptionNullStrategy()
            {
				ValidationBinding.DisplayStrategies.RemoveStrategy(null);
            }
        [Test]
            public void Simple()
            {
            
            ValidationBinding.DisplayStrategies.Clear();
            var mockErrorDisplayStrategy = new MockErrorDisplayStrategy();
			ValidationBinding.DisplayStrategies.AddStrategy(mockErrorDisplayStrategy);
            Assert.IsTrue(ValidationBinding.DisplayStrategies.Contains(mockErrorDisplayStrategy));
			ValidationBinding.DisplayStrategies.RemoveStrategy(mockErrorDisplayStrategy);
            Assert.IsFalse(ValidationBinding.DisplayStrategies.Contains(mockErrorDisplayStrategy));

            }
        }

        public class MockErrorDisplayStrategy:IErrorDisplayStrategy
        {
            

            public void DisplayError(BindingExpressionBase bindingExpressionBase, FrameworkElement frameworkElement, string errorMessage)
            {
                throw new NotImplementedException();
            }

            public void ClearError(FrameworkElement element)
            {
                throw new NotImplementedException();
            }

            public bool CanHandleTarget(FrameworkElement rule)
            {
                throw new NotImplementedException();
            }
        }
    }
}
